package cn.net.ecode.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * @version 2014-8-19
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class EntityUtils {

	private static final Logger logger = LoggerFactory
			.getLogger(EntityUtils.class);

	private static final Map<String, Map<String, List>> classMap = Maps
			.newHashMap();

	private static final String FIELDS_NAME = "fields";
	private static final String METHODS_NAME = "methods";

	public static <T> List<T> conver(List<Map<String, String>> list, Class<T> t)
			throws Exception {
		if (list == null) {
			return Lists.newArrayList();
		}
		List<T> resultList = Lists.newArrayList();
		for (Map<String, String> map : list) {
			resultList.add(conver(map, t));
		}
		return resultList;
	}

	public static <T> T conver(Map<String, String> map, Class<T> t)
			throws Exception {

		T obj = t.newInstance();

		Map<String, List> classMsg = classMap.get(t.getName());
		if (classMsg == null) {
			classMsg = initEntity(t);
			classMap.put(t.getName(), classMsg);
		}

		List<Field> fields = classMsg.get(FIELDS_NAME);
		List<Method> methods = classMsg.get(METHODS_NAME);

		for (int i = 0; i < fields.size(); i++) {
			Field field = fields.get(i);
			Method method = methods.get(i);
			String value = map.get(field.getName());
			if (value == null) {
				continue;
			}
			invoke(obj, field, method, value);
		}
		return obj;
	}

	/**
	 * 
	 * @param <T>
	 * @param obj
	 *            实体
	 * @param field
	 *            属性
	 * @param method
	 *            方法
	 * @param value
	 *            值
	 * @throws Exception
	 */
	private static <T> void invoke(T obj, Field field, Method method,
			String value) throws Exception {

		if (field.getType().equals(int.class)
				|| field.getType().equals(Integer.class)) {
			// int类型
			method.invoke(obj, new Object[] { Integer.parseInt(value) });
			return;
		}
		if (field.getType().equals(long.class)
				|| field.getType().equals(Long.class)) {
			// long类型
			method.invoke(obj, new Object[] { Long.parseLong(value) });
			return;
		}

		if (field.getType().equals(float.class)
				|| field.getType().equals(Float.class)) {
			// float类型
			method.invoke(obj, new Object[] { Float.parseFloat(value) });
			return;
		}

		if (field.getType().equals(double.class)
				|| field.getType().equals(Double.class)) {
			// double类型
			method.invoke(obj, new Object[] { Double.parseDouble(value) });
			return;
		}

		if (field.getType().equals(Date.class)) {
			// double类型
			String pattern = "";
			if (value.matches("\\d{4}-\\d{2}-\\d{2}")) {
				pattern = "yyyy-MM-dd";
			} else if (value
					.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
				pattern = "yyyy-MM-dd kk:mm:ss";
			} else if (value.matches("\\d{8}")) {
				pattern = "yyyyMMdd";
			} else if (value.matches("\\d{8} \\d{2}:\\d{2}:\\d{2}")) {
				pattern = "yyyyMMdd kk:mm:ss";
			} else {
				pattern = "yyyy-MM-dd";
			}
			method.invoke(obj,
					new Object[] { new SimpleDateFormat(pattern).parse(value) });
			return;
		}

		if (field.getType().equals(String.class)) {
			method.invoke(obj, value);
			return;
		}

		throw new Exception("type:" + field.getType().getName()
				+ " is not config.");

	}

	/**
	 * 获取实体的set属性和方法
	 * 
	 * @param t
	 *            实体
	 * @return
	 */
	private static <T> Map<String, List> initEntity(Class<T> t) {
		Field[] declaredFields = t.getDeclaredFields();

		List<Field> fields = Lists.newArrayList();
		List<Method> methods = Lists.newArrayList();

		for (Field field : declaredFields) {
			String fieldName = field.getName();
			String methodName = "set" + fieldName.substring(0, 1).toUpperCase()
					+ fieldName.substring(1);
			try {
				Method method = t.getMethod(methodName, field.getType());
				fields.add(field);
				methods.add(method);
			} catch (Exception e) {
				logger.warn(e.getMessage());
			}
		}

		Map<String, List> classMap = Maps.newHashMap();
		classMap.put(FIELDS_NAME, fields);
		classMap.put(METHODS_NAME, methods);

		return classMap;
	}
}
